from typing import List, Tuple, Iterable

from bson import ObjectId
from loguru import logger
from pymongo import UpdateOne

from ioservice.common.mongo import insert_models, find_many_models, bulk_write, count_documents, aggregate_docs, \
    delete_models
from ioservice.const import activity_register_col, activity_institution_col
from models.activity import ActivityRegister, ActivityInstitution
from utils.dateutil import date_now


async def bulk_insert_institutions(registers: List[ActivityInstitution]):
    for r in registers:
        r.create_time = date_now()
    inserted_ids = await insert_models(activity_institution_col, registers)
    return inserted_ids


async def bulk_replace_institution_records(records: List[ActivityInstitution]):
    opts = list()

    logger.info(f"records:{records}")

    for r in records:
        r.update_time = date_now()
        doc = r.mongo(exclude_unset=True, exclude_none=True)
        opts.append(UpdateOne({"institution_id": r.institution_id, "activity_id": r.activity_id}, {"$set": doc}, upsert=True))
    result = await bulk_write(activity_institution_col, opts)
    return result.modified_count


async def find_institution_records_by_query(query, sort=None, offset=None, size=None, fields=None):
    return await find_many_models(activity_institution_col, ActivityInstitution, query, sort, offset, size, fields)


async def find_institution_records_by_combined_ids(ids: Iterable[Tuple[str, str]], sort=None, fields=None):
    """
    根据联合id获取校友与活动的关系
    :param ids: List[Tuple] [(person_id, activity_id)]
    :return:
    """
    query = {"$or": [{"institution_id": ObjectId(i[0]), "activity_id": ObjectId(i[1])} for i in ids]}
    logger.info(f"after_alter_institution_record::update_alumni_computing_fields people number: {query}")

    return await find_institution_records_by_query(query, sort, 0, 0, fields=fields)


async def count_institution_records(query):
    return await count_documents(activity_institution_col, query)


async def aggregate_activity_institution_raw(pipeline):
    return await aggregate_docs(activity_institution_col, pipeline)


async def delete_activity_institution_by_query(query):
    return await delete_models(activity_institution_col, query)
